home *** CD-ROM | disk | FTP | other *** search
- From: decvax!vax135!hou3c!ka
- Date: Mon, 21 Jan 85 22:39:03 est
- Newsgroups: mod.sources
- Subject: Vnews part 6
-
- # Welcome to vnews release 2.11-B 1/17/85.
- # This is part 6 out of 7.
- # Feed me into sh (NOT csh).
-
- if test ! -d postnews
- then mkdir postnews
- fi
-
- if test ! -d vnews
- then mkdir vnews
- fi
-
- cat > postnews/postnm5.c <<\!E!O!F!
- /*
- * STRING SCANNING ROUTINES:
- * These routines act on a subject string which is pointed to by scanp.
- *
- * scchr Skip over characters contained in string.
- * scnchr Skip over characters not in string.
- * skipbl Skip over spaces, tabs, and newlines.
- * scomment Skip to the end of a comment.
- * scqnchr Like scnchr, but skips over any char if inside quotes.
- * skipsw Skip over spaces, tabs, newlines, and comments.
- * parseaddr Parse an address, setting up pointers to various parts.
- * getval Return the characters between two pointers.
- *
- * Copyright 1984 by Kenneth Almquist. All rights reserved.
- * Permission is granted for anyone to use and distribute, but not
- * sell, this program provided that this copyright notice is retained.
- */
-
- #include "postnm.h"
-
- char *scanp;
-
- scchr(chars)
- char *chars;
- {
- int flag = 0;
-
- while (*scanp && index(chars, *scanp)) {
- flag++;
- scanp++;
- }
- return flag;
- }
-
-
- scnchr(chars)
- char *chars;
- {
- int flag = 0;
-
- while (index(chars, *scanp) == NULL) {
- flag++;
- scanp++;
- }
- return flag;
- }
-
-
-
- skipbl() {
- register char c;
-
- while ((c = *scanp) == ' ' || c == '\t' || c == '\n')
- scanp++;
- }
-
-
-
- scomment() {
- int nest;
- register char *p;
-
- if (*(p = scanp) != '(')
- return 0;
- nest = 0;
- for (;;) {
- if (*p == '(')
- nest++;
- else if (*p == ')') {
- if (--nest == 0)
- break;
- } else {
- if (*p == '\\')
- p++;
- if (*p == '\0')
- jsynerr("Nonterminated comment");
- }
- p++;
- }
- scanp = p;
- return 1;
- }
-
-
- scqnchr(chars)
- char *chars;
- {
- register char *p = scanp;
-
- for (;;) {
- if (*p == '"') {
- p++;
- while (*p != '"') {
- if (*p == '\\')
- p++;
- if (*p++ == '\0')
- jsynerr("Nonterminated string");
- }
- } else {
- if (index(chars, *p))
- break;
- }
- p++;
- }
- if (p == scanp)
- return 0;
- else {
- scanp = p;
- return 1;
- }
- }
-
-
-
- skipws(chars)
- char *chars;
- {
- for (;;) {
- if (*scanp == '(')
- scomment();
- else if (*scanp == '\0' || index(chars, *scanp) == NULL)
- break;
- scanp++;
- }
- }
-
-
-
- /*
- * Parse an address.
- */
-
- char *begreal, *endreal; /* real name */
- char *begaddr, *endaddr; /* machine address */
- char *beglocal, *endlocal; /* local part */
- char *begdomain, *enddomain; /* domain part */
-
- parseaddr() {
- char *startp = scanp;
- char *p;
-
- begreal = begdomain = NULL;
- if (*scanp == '.')
- syntax: jsynerr("Illegal address syntax");
- begaddr = beglocal = scanp;
- if (*scanp == '<') {
- routeaddr:
- scanp++;
- skipbl();
- begaddr = beglocal = scanp;
- scqnchr(":>");
- if (*scanp == ':') {
- scanp++;
- skipbl();
- beglocal = scanp;
- scqnchr(">");
- }
- if (*scanp != '>')
- goto syntax;
- scanp = beglocal;
- scqnchr("@>");
- endlocal = scanp;
- while (index(" \t\n", *(endlocal - 1)))
- endlocal--;
- if (endlocal <= beglocal)
- goto syntax;
- if (*scanp == '@') {
- scanp++;
- skipbl();
- begdomain = scanp;
- scqnchr(">");
- enddomain = scanp;
- while (index(" \t\n", *(enddomain - 1)))
- enddomain--;
- if (enddomain <= begdomain)
- goto syntax;
- }
- if (*scanp != '>')
- goto syntax;
- scanp++;
- } else {
- scqnchr(" \t\n@(,<");
- if (scanp == startp)
- jsynerr("Program bug");
- endlocal = scanp;
- skipbl();
- if (*scanp == '@') {
- scanp++;
- skipbl();
- begdomain = scanp;
- if (scnchr(" \t\n(,<") == 0)
- goto syntax;
- enddomain = scanp;
- if (enddomain[-1] == '.')
- goto syntax;
- } else {
- do p = scanp, skipbl();
- while (scqnchr(" \t\n@(,<"));
- if (*scanp != '<') {
- scanp = endlocal;
- } else {
- begreal = beglocal, endreal = p;
- goto routeaddr;
- }
- }
- }
- if (begdomain)
- endaddr = enddomain;
- else
- endaddr = endlocal;
- if (begreal == NULL) {
- p = scanp;
- skipbl();
- if (*scanp != '(') {
- scanp = p;
- } else {
- begreal = scanp + 1;
- scomment();
- endreal = scanp;
- scanp++; /* skip over ')' */
- }
- }
- }
-
-
-
- char *
- getval(p, q, buf)
- char *p, *q, *buf;
- {
-
- if (buf == NULL)
- buf = ckmalloc(q - p + 1);
- bcopy(p, buf, q - p);
- buf[q - p] = '\0';
- return buf;
- }
- !E!O!F!
-
- cat > postnews/postreply.c <<\!E!O!F!
- /*
- * This program handles replies and followups for vnews.
- * Synopsys:
- * reply -r file # mail a reply
- * reply -f file # generate a followup
- */
-
- #include <stdio.h>
- #include <sys/types.h>
- #include "config.h"
- #include "newsdefs.h"
- #include "libextern.h"
- #include "arthead.h"
- #include <sys/stat.h>
- #include <signal.h>
- #include <ctype.h>
-
-
- #define NOPOST 22
-
- int followup;
- char *original;
- char *references;
- int vnews;
- struct arthead h;
- int checksum;
- int nchars;
- FILE *tfp;
- char tempfile[16];
- char tempout[16];
- int outfd;
-
- FILE *ckfopen();
- char *savestr();
- int nopost();
-
-
-
- main(argc, argv)
- char **argv;
- {
- int c;
- int pid;
- extern char *optarg;
-
- signal(SIGQUIT, SIG_IGN);
- while ((c = getopt(argc, argv, "r:f:v")) != EOF) {
- switch (c) {
- case 'r':
- followup = 0;
- original = optarg;
- break;
- case 'f':
- followup = 1;
- original = optarg;
- break;
- case 'v':
- vnews = 1;
- break;
- }
- }
- if (original == NULL)
- xerror("-f or -r must be specified");
-
- signal(SIGINT, nopost);
-
- pathinit();
- getuser();
-
- writetemp(followup);
-
- edit();
- if (samefile())
- nopost();
-
- /* fork off a child and let parent terminate */
- signal(SIGINT, SIG_IGN);
- signal(SIGQUIT, SIG_IGN);
- signal(SIGHUP, SIG_IGN);
- #ifdef SIGTSTP
- signal(SIGTSTP, SIG_IGN); /* I hope this works */
- #endif
- if ((pid = fork()) == -1)
- fprintf(stderr, "postreply: can't fork\n");
- if (pid > 0)
- _exit(0);
-
- nice(4);
- sprintf(bfr, "%s.BAK", tempfile);
- unlink(bfr);
-
- postit();
- xxit(0);
- }
-
-
- /*
- * Print a recorded message warning the poor luser what he is doing
- * and demand that he understands it before proceeding. Only do
- * this for newsgroups listed in LIBDIR/recording.
- */
- recording(ngrps)
- char *ngrps;
- {
- char recbuf[BUFLEN];
- FILE *fd;
- char nglist[BUFLEN], fname[BUFLEN];
- int c, n, yes;
-
- sprintf(recbuf, "%s/recording", LIB);
- fd = fopen(recbuf, "r");
- if (fd == NULL)
- return 0;
- while ((fgets(recbuf, sizeof recbuf, fd)) != NULL) {
- sscanf(recbuf, "%s %s", nglist, fname);
- if (ngmatch(ngrps, nglist)) {
- fclose(fd);
- if (fname[0] == '/')
- strcpy(recbuf, fname);
- else
- sprintf(recbuf, "%s/%s", LIB, fname);
- fd = fopen(recbuf, "r");
- if (fd == NULL)
- return 0;
- while ((c = getc(fd)) != EOF)
- putc(c, stderr);
- fclose(fd);
- fprintf(stderr, "Do you understand this? Hit <return> to proceed, <BREAK> to abort: ");
- n = read(2, recbuf, BUFLEN);
- c = recbuf[0];
- yes = (c=='y' || c=='Y' || c=='\n' || c=='\n' || c==0);
- if (n <= 0 || !yes)
- return -1;
- else
- return 0;
- }
- }
- fclose(fd);
- return 0;
- }
-
-
-
- /*
- * Generate replies and followups.
- */
-
-
- writetemp() {
- FILE *artfp;
- char subj[132];
- char *p;
- char *replyname();
-
- checksum = 0;
- nchars = 0;
- artfp = ckfopen(original, "r");
- if (gethead(&h, artfp) == NULL)
- xerror("Original article has garbled header");
- fclose(artfp);
-
-
- scopyn(h.h_title, subj, 128);
- if (!prefix(subj, "Re:") && !prefix(subj, "re:")) {
- strcpy(bfr, subj);
- sprintf(subj, "Re: %s", bfr);
- }
-
- p = h.h_nbuf;
- if (hset(h.h_followto))
- p = h.h_followto;
- strcpy(bfr, p);
- launder(bfr);
- if (followup && recording(bfr))
- nopost();
-
- gentemp(tempfile);
- tfp = ckfopen(tempfile, "w");
-
- wstr("Command: %s\n", followup? "followup" : "reply");
- wstr("Newsgroups: %s\n", bfr);
- wstr("To: %s\n", replyname(&h, bfr));
- wstr("Subject: %s\n", subj);
- if (hset(h.h_keywords))
- wstr("Keywords: %s\n", h.h_keywords);
- wstr("Distribution: %s\n", hset(h.h_distribution)? h.h_distribution : "");
- bfr[0] = 0; /* References */
- if (hset(h.h_references)) {
- strcpy(bfr, h.h_references);
- strcat(bfr, " ");
- }
- strcat(bfr, h.h_ident);
- references = savestr(bfr);
- wstr("References: %s\n", bfr);
- wstr("\n");
- fclose(tfp);
- }
-
-
-
- wstr(fmt, a1, a2, a3, a4)
- char *fmt;
- {
- char buf[1024];
- register char *p;
-
- sprintf(buf, fmt, a1, a2, a3, a4);
- for (p = buf ; *p ; ) {
- checksum += *p++;
- nchars++;
- }
- fputs(buf, tfp);
- }
-
-
-
- /*
- * Check to see if the newsgroup is moderated. If so, the moderator's
- * name is returned in moderator.
- */
- #ifdef notdef
- check_mod(newsgroups, moderator)
- char *newsgroups;
- char *moderator;
- {
- register FILE *fd;
- char ng[64], mod[BUFLEN];
-
- sprintf(bfr, "%s/%s", LIB, "moderators");
- if ((fd = fopen(bfr, "r")) == NULL)
- return 0;
- while (1) {
- if (fgets(bfr, LBUFLEN, fd) == NULL) {
- fclose(fd);
- return 0;
- }
- twosplit(bfr, ng, mod);
- if (ngmatch(newsgroups, ng)) {
- strcpy(moderator, mod);
- fclose(fd);
- return 1;
- }
- }
- }
-
-
-
- /*
- * Split a line of the form
- * text whitespace text
- * into two strings. Also trim off any trailing newline.
- * This is destructive on src.
- */
- twosplit(src, dest1, dest2)
- char *src, *dest1, *dest2;
- {
- register char *p;
-
- nstrip(src);
- for (p=src; isalnum(*p) || ispunct(*p); p++)
- ;
- *p++ = 0;
- for ( ; isspace(*p); p++)
- ;
- strcpy(dest1, src);
- strcpy(dest2, p);
- }
- #endif
-
-
-
- edit() {
- char *p;
- int pid;
- int status;
- char *arg[5];
- register char **ap;
- char *getenv(), *rindex();
-
- if ((arg[0] = getenv("EDITOR")) == NULL)
- arg[0] = DFTEDITOR;
- if ((p = rindex(arg[0], '/')) != NULL)
- p++;
- else
- p = arg[0];
- ap = &arg[1];
- if (strcmp(p, "vi") == 0) {
- *ap++ = "+";
- *ap++ = tempfile;
- *ap++ = original;
- } else if (strcmp(p, "gmacs") == 0
- || strcmp(p, "gemacs") == 0
- || strcmp(p, "gem") == 0) {
- *ap++ = original;
- *ap++ = tempfile;
- } else {
- *ap++ = tempfile;
- *ap++ = original;
- }
- *ap = NULL;
-
- if ((pid = fork()) == -1)
- xerror("Can't fork");
- if (pid == 0) {
- signal(SIGQUIT, SIG_DFL);
- execvp(arg[0], arg);
- _exit(124);
- }
- signal(SIGINT, SIG_IGN);
- status = pwait(pid);
- if (status == 124 << 8)
- xerror("Can't exec %s", arg[0]);
- }
-
-
-
- samefile() {
- struct stat statb;
- register FILE *fp;
- register int c;
-
- if (stat(tempfile, &statb) < 0)
- xerror("%s has vanished!", tempfile);
- if (statb.st_size == 0L)
- return 1;
- if (statb.st_size != nchars)
- return 0;
- fp = ckfopen(tempfile, "r");
- while ((c = getc(fp)) != EOF)
- checksum -= c;
- return (checksum == 0);
- }
-
-
-
- postit() {
- int artfd;
- int i;
-
- gentemp(tempout);
- if ((outfd = creat(tempout, 0644)) < 0) {
- fprintf(stderr, "\7\nCan't create %s\nreply failed\n\7", tempout);
- xxit(1);
- }
- if (followup)
- writestr("Subject: followup failed\n\n", outfd);
- else
- writestr("Subject: reply failed\n\n", outfd);
-
- if (runpost()) {
- if ((artfd = open(tempfile, 0)) < 0)
- writestr("postreply: can't reopen article\n", outfd);
- else {
- writestr("\nYour article follows:\n", outfd);
- while ((i = read(artfd, bfr, LBUFLEN)) > 0)
- write(outfd, bfr, i);
- close(artfd);
- }
- close(outfd);
- unlink(tempfile);
- close(0);
- if (open(tempout, 0) != 0) {
- fprintf(stderr, "\7Fatal error in reply!\nCan't reopen %s\7\n", tempout);
- exit(1);
- }
- #ifdef MAILER
- execl(MAILER, MAILER, username, (char *)0);
- #endif
- execl("/bin/mail", "mail", username, (char *)0);
- fprintf(stderr, "\7Fatal error in reply!\nCan't exec mail program!\7\n");
- exit(1);
- }
- }
-
-
-
- runpost() {
- int pid;
- int status;
- int fildes[2];
- FILE *fp;
- int inewsfail;
- static char prog[] = POSTNM;
-
- if (pipe(fildes) < 0) {
- writestr("can't create pipe\n", outfd);
- return -1;
- }
- while ((pid = fork()) == -1)
- sleep(10);
- if (pid == 0) {
- #ifdef notdef
- close(0);
- if (open(tempfile, 0) != 0) {
- sprintf(bfr, "postreply: can't open %s\n", tempfile);
- writestr(bfr, outfd);
- _exit(2);
- }
- #endif
- if (fildes[1] != 1) {
- close(1);
- dup(fildes[1]);
- close(fildes[1]);
- }
- close(fildes[0]);
- close(2);
- dup(1);
- execl(prog, prog, "-wiR", references, tempfile, (char *)0);
- writestr("postreply: can't exec postnm\n", 1);
- _exit(2);
- }
- close(fildes[1]);
- fp = fdopen(fildes[0], "r");
- inewsfail = 0;
- while (fgets(bfr, LBUFLEN, fp) != NULL) {
- writestr(bfr, outfd);
- if (prefix(bfr, "inews:"))
- inewsfail = 1;
- }
- status = pwait(pid);
- if (status != 0 || inewsfail) {
- if ((status & 0377) == 0)
- sprintf(bfr, "Exit status %d from postnm\n", status >> 8);
- else
- sprintf(bfr, "postreply: postnm died with signal %d\n", status & 077);
- writestr(bfr, outfd);
- return -1;
- }
- return 0;
- }
-
-
- #ifdef notdef
- /*
- * Save a copy of the article in the users NEWSARCHIVE file.
- * The article is saved only if the user explicitly sets NEWSARCHIVE.
- * Currently, we save both news and mail replies, which is
- * rather questionable.
- */
- save_article()
- {
- register FILE *in, *out;
- register int c;
- time_t timenow, time();
- char *today, *ctime();
- char *ccname;
-
- if ((ccname = getenv("NEWSARCHIVE")) == NULL || ccname[0] == '\0')
- return 0;
- if ((in = fopen(tempfile, "r")) == NULL) {
- writestr("Can't reopen temp file for article save\n", outfd);
- return -1;
- }
- if ((out = fopen(ccname, "a")) == NULL) {
- sprintf(bfr, "Can't open %s to save article\n", ccname);
- writestr(bfr, outfd);
- return -1;
- }
- timenow = time((time_t)0);
- today = ctime(&timenow);
- fprintf(out, "From postreply %s", today);
- while ((c=getc(in)) != EOF)
- putc(c, out);
- putc('\n', out);
- fclose(in);
- fclose(out);
- return 0;
- }
- #endif
-
-
- writestr(s, fd)
- char *s;
- int fd;
- {
- write(fd, s, strlen(s));
- }
-
-
- pwait(pid) {
- int status;
-
- while (wait(&status) != pid);
- return status;
- }
-
-
-
- gentemp(s)
- char s[16];
- {
- strcpy(s, "/tmp/repXXXXXX");
- mktemp(s);
- }
-
-
-
- xerror(fmt, a1, a2, a3, a4)
- char *fmt;
- {
- int c;
-
- fputs("postreply: ", stderr);
- fprintf(stderr, fmt, a1, a2, a3, a4);
- fputs("\nContinue?", stderr);
- while ((c = getchar()) != '\n' && c != EOF);
- xxit(1);
- }
-
-
-
- xxit(status) {
- if (tempfile[0])
- unlink(tempfile);
- if (tempout[0])
- unlink(tempout);
- exit(status);
- }
-
-
-
- nopost() {
- xxit(NOPOST);
- }
- !E!O!F!
-
- cat > vnews/2.11features <<\!E!O!F!
- + Erase and kill processing performed on count.
-
- + Newsgroups presented in the order in which they appear in .newsrc. This
- allows newsgroup presentation order to be set on an individual basis.
-
- + Articles are now presented grouped by discussion. Within a discussion,
- articles are sorted by date.
-
- + An index page is now available. The -A option will cause the index page
- to be shown on entry to each group. Scrolling off the end of the index
- page using space gets you to the first article in the newsgroup. You can
- execute practically all vnews commands on the index page; the scrolling
- commands scroll the index page and the other commands apply to the current
- article. The 'a' command will toggle you to/from the index page.
-
- + There is now an article list stack. The "N newsgroup" command will save
- the current newsgroup on the stack so that when you reach the end of the
- newsgroup all the articles in the newsgroup you just left will still be
- there. Currently, the "N newsgroup" command empties the stack before
- beginning in order to keep things simple for the user. The parent and
- '<' commands create an article list containing one article. Unless the
- current article list contains a single article, the current article list
- will be saved on the stack, so that you will automaticly return to where
- you were.
-
- + The "N newsgroup command" will now work even with unsubscribed groups.
- !E!O!F!
-
- cat > vnews/ToDo <<\!E!O!F!
- Read in next newsgroups during idle time. May not be able to store in
- memory, but could write record to temp file, and do sort when actually
- enter group.
-
- Chdir to spool directory while running.
-
- Add .rnlock checking. (Use .newsrc.lck since rn use SIGEMT.)
-
- Make N- get real previous group.
-
- Make jd command save discussion for later.
-
- Make t command get you to first unread article.
-
- Make xerror do a longjmp to the code that resets the tty modes and updates
- the .newsrc file. Save a copy of the .newsrc file in .newsrc.bak.
-
- !E!O!F!
-
- cat > vnews/artseq.c <<\!E!O!F!
- #include "vnews.h"
-
- #ifdef SMALL /* try to avoid running out of core */
- #define MAXNUMARTS 100 /* max arts we can read in one newsgroup */
- #endif
-
- static struct svartlist alstack[10]; /* stack of article lists */
- struct svartlist *alptr = alstack; /* stack pointer for above */
- static int readmode = NEXT; /* currently unused */
- static struct ngentry *ngindex; /* current location in .newsrc file */
-
-
- /*
- * set or clear the unread article flag
- */
- setnew(on) {
- if (alptr->al_type != SVNEWSGROUP)
- return;
- if (on)
- setunread(curart->i_artnum);
- else
- clrunread(curart->i_artnum);
- }
-
-
- /*
- * Go to a particular article number
- */
-
- setartno(num)
- int num;
- {
- if (num <= 0) {
- msg("Bad article no.");
- return;
- }
- if (num > numthisng) {
- msg("Not that many articles.");
- return;
- }
- curart = &thisng[num - 1];
- setupart();
- }
-
-
- /*
- * Advance the counter to the next unread article.
- */
- nextart(count, zapthem)
- {
- if (count <= 0)
- return FALSE;
- while (--count >= 0) {
- if (zapthem)
- setnew(0);
- if (readmode == SPEC || xflag) {
- curart++, curind++;
- } else {
- while (++curart, ++curind <= numthisng && !isunread(curart->i_artnum))
- ;
- }
- if (curind > numthisng)
- return getnxtng(FORWARD);
- }
- setupart();
- return FALSE;
- }
-
-
- /*
- * Vnews article list stack. Pushal(type) pushes the current article list
- * onto the stack. Type is the type of the replacement article list. Popal
- * restores an article list from the stack. Setupart should be called after
- * popal.
- */
-
- struct alsave {
- int a_numthisng;
- int a_curind;
- struct ngentry *a_curng;
- int a_iwartlin;
- int a_indexpg;
- int a_maxartno;
- };
-
-
- pushal(type) {
- struct alsave als;
-
- if (alptr >= alstack + 9) {
- msg("newsgroups nested too deeply");
- alptr->al_type = type;
- return;
- }
- alptr->al_tfoffset = tfoffset;
- als.a_numthisng = numthisng;
- als.a_curind = curind;
- als.a_curng = curng;
- als.a_iwartlin = indexwin.w_artlin;
- als.a_indexpg = indexpg;
- als.a_maxartno = maxartno;
- fseek(tfp, (long)tfoffset, 0);
- fwrite((char *)&als, sizeof als, 1, tfp);
- fwrite((char *)thisng, sizeof *thisng, numthisng, tfp);
- tfoffset = ftell(tfp);
- tflinno = -1;
- (++alptr)->al_type = type;
- }
-
-
- popal() {
- struct alsave als;
-
- tfoffset = (--alptr)->al_tfoffset;
- fseek(tfp, (long)tfoffset, 0);
- fread((char *)&als, sizeof als, 1, tfp);
- numthisng = als.a_numthisng;
- curind = als.a_curind;
- indexwin.w_artlin = als.a_iwartlin;
- indexpg = als.a_indexpg;
- fread((char *)thisng, sizeof *thisng, numthisng, tfp);
- indexwin.w_force = 2;
- tflinno = -1;
- if ((alptr+1)->al_type == SVNEWSGROUP)
- setupgrp(als.a_curng, als.a_maxartno);
- setartno(curind);
- }
-
-
-
- switchng(ngp) /* go to specific newsgroup */
- struct ngentry *ngp;
- {
- if (alptr >= alstack + 8) {
- msg("Nesting too deep.");
- return;
- }
- if (alptr->al_type == SVARTICLE)
- popal();
- pushal(SVNEWSGROUP);
- readinng(ngp, 1);
- if (numthisng <= 0) {
- popal();
- msg("group? %s: empty", ngp->ng_name);
- } else {
- ngrp++;
- }
- setupart();
- }
-
-
- spclgrp(dp, a)
- DPTR dp;
- struct artrec *a;
- {
- if (alptr->al_type != SVARTICLE)
- pushal(SVARTICLE);
- scopyn(a->a_title, thisng[0].i_title, 36);
- scopyn(a->a_from, thisng[0].i_from, 29);
- thisng[0].i_nlines = a->a_nlines;
- thisng[0].i_artnum = a->a_group[0].a_artno;
- thisng[0].i_dptr = dp;
- numthisng = 1;
- curart = thisng;
- setupart();
- sprintf(filename, "%s/%s", SPOOL, a->a_file);
- indexpg = 0;
- }
-
-
- getnxtng(direct) {
- if (direct == FORWARD && alptr > alstack) { /* al stack stuff */
- popal();
- setupart();
- /* advance to next article if current one read */
- if ((alptr+1)->al_type == SVNEWSGROUP
- && isunread(curart->i_artnum) == 0)
- return nextart(1, 0);
- return FALSE;
- }
- while (alptr > alstack) /* for backwards, clear al stack */
- popal();
-
- for (;;) {
- if (direct == FORWARD) {
- if ((ngindex = nextgrp(ngindex)) == NULL) {
- quitflg++;
- return TRUE;
- }
- } else {
- if ((ngindex = prevgrp(ngindex)) == NULL) {
- msg("Can't back up.");
- direct = FORWARD;
- continue;
- }
- }
- if (ngindex->ng_unsub || !wewant(ngindex->ng_name))
- continue;
- readinng(ngindex, 0);
- if (numthisng > 0)
- break;
- }
- ngrp++;
- setupart();
- return FALSE;
- }
-
-
- setupart() {
- if (ngrp) {
- pngsize = maxartno;
- if (Aflag)
- indexpg = 1;
- if (indexpg)
- ngrp = 0;
- }
- curind = curart - thisng + 1;
- #ifdef DEBUG
- fprintf(stderr, "getnextart settles on #%d, bit %d\n", curind, curart->i_artnum);
- #endif
- dirname(curng->ng_name, filename);
- sprintf(filename + strlen(filename), "/%d", curart->i_artnum);
- if (fp != NULL) {
- fclose(fp);
- fp = NULL;
- }
- news = TRUE;
- indexwin.w_force |= 1;
- erased = 0;
- }
-
- /*
- * Read in the newsgroup.
- */
- readinng(ngp, all)
- struct ngentry *ngp;
- {
- register struct artinfo *ip;
- struct artrec a, a2;
- DPTR dp, dp2;
- int ngnum = ng_num(ngp);
- ARTNO bit, oldbit;
- int first;
- int i;
- static int thisngsize = 20;
- int cmppart();
- char *ckmalloc(), *realloc();
-
- if (news) {
- curflag = CURHOME;
- #ifdef CURSES
- move(0, 0); /* let user know we are thinking */
- refresh();
- #else
- _amove(0, 0); /* let user know we are thinking */
- vflush();
- #endif
- }
- if (thisng == NULL) {
- thisng = ckmalloc(20 * sizeof thisng[0]);
- }
- numthisng = 0;
- oldbit = 0;
- first = 1;
- BKWD_GROUP(ngnum, bit, dp, a) {
- if (first) {
- setupgrp(ngp, bit);
- first = 0;
- }
- while (--oldbit > bit) /* clear intermediate bits */
- clrunread(oldbit);
- oldbit = bit;
- if (bit < minartno && !all)
- break;
- if (!(all || isunread(bit)))
- continue;
- /* later: rethink the handling of all */
- if ((a.a_flags & A_NOFILE) || !aselect(&a, 0) || haveunsub(dp)) {
- skipit: clrunread(bit);
- continue;
- }
- a2.a_subtime = a.a_subtime;
- for (dp2 = a.a_parent, i = 0 ; dp2 != DNULL && ++i < 100 ; dp2 = a2.a_parent) {
- if (haveunsub(dp2))
- goto skipit;
- readrec(dp2, &a2);
- }
- if (i == 100)
- fprintf(stderr, "Parent loop %s %s \r\n", a.a_ident, a2.a_ident); /*DEBUG*/
- if (numthisng >= thisngsize) {
- thisngsize += 4;
- if ((thisng = realloc((char *)thisng, thisngsize * sizeof thisng[0])) == NULL)
- xerror("Out of space");
- }
- ip = &thisng[numthisng];
- ip->i_artnum = bit;
- ip->i_subtime = a.a_subtime;
- ip->i_basetime = a2.a_subtime;
- scopyn(a.a_title, ip->i_title, 37);
- scopyn(a.a_from, ip->i_from, 29);
- ip->i_dptr = dp;
- ip->i_nlines = a.a_nlines;
- #ifndef DEBUG
- if (debugging > 1)
- #endif
- fprintf(stderr, "storing %d in %d, subtime %d\n", bit, numthisng, ip->i_subtime);
- numthisng++;
- #ifdef MAXNUMARTS
- if (numthisng >= MAXNUMARTS) {
- printf("Warning - more than %d new articles, missing some.\n", MAXNUMARTS);
- goto nomore; /* exit loop */
- }
- #endif
- }
- while (--oldbit >= minartno)
- clrunread(oldbit);
- nomore:
- if (numthisng > 0) {
- qsort((char *)thisng, numthisng, sizeof thisng[0], cmppart);
- }
- curart = thisng; /* go to start of group */
- indexwin.w_artlin = 0;
- indexwin.w_force = 2;
- }
-
-
- /*
- * Check whether we ahve unsubscribed to the discussion.
- */
- haveunsub(dp)
- DPTR dp;
- {
- register DPTR *p;
- register int i;
-
- for (i = ndunsub, p = dunsub ; --i >= 0 ; p++)
- if (*p == dp)
- return 1;
- return 0;
- }
-
-
- /*
- * Compare two articles, and determine if they are in the same discussion.
- * If not, we sort by time of base article.
- */
- cmppart(n1, n2)
- register struct artinfo *n1, *n2;
- {
- if (n1->i_basetime > n2->i_basetime)
- return 1; /* different discussions */
- else if (n1->i_basetime < n2->i_basetime)
- return -1; /* different discussions */
- else if (n1->i_subtime > n2->i_subtime)
- return 1; /* same discussion */
- else if (n1->i_subtime < n2->i_subtime)
- return -1; /* same discussion */
- else
- return 0; /* same discussion */
- }
-
-
-
- /*
- * Return TRUE if the user has not ruled out this article.
- */
- aselect(a, insist)
- register struct artrec *a;
- int insist;
- {
- extern char *titles[];
-
- if (insist)
- return TRUE;
- if (tflag && !titmat(a->a_title, titles))
- return FALSE;
- if (aflag && a->a_rectime < atime)
- return FALSE;
- if (a->a_ngroups > 1 && !rightgroup(a))
- return FALSE;
- if (fflag && a->a_parent != DNULL)
- return FALSE;
- return TRUE;
- }
-
-
-
- /*
- * Code to avoid showing multiple articles for vnews.
- * Works even if you exit vnews.
- * Returns nonzero if we should show this article.
- */
- rightgroup(a)
- struct artrec *a;
- {
- int i, flag;
- struct ngentry *ngp;
-
- flag = 1;
- for (i = 0 ; i < a->a_ngroups ; i++) {
- ngp = ngtable + a->a_group[i].a_ngnum;
- if (ngp == curng)
- return flag;
- if (wewant(ngp->ng_name) && ngp->ng_unsub == 0) {
- flag = 0;
- }
- }
- /* "Can't happen" */
- return 1;
- }
-
-
-
- /*
- * Return true if the newsgroup was specified in the -n option.
- */
-
- wewant(name)
- char *name;
- {
- return ngmatch(name, sublist);
- }
- !E!O!F!
-
- cat > vnews/curterm.c <<\!E!O!F!
- /*
- * Additions to curses.
- */
-
- #include <stdio.h>
- #include <curses.h>
-
- /*
- * move to the bottom of the screen.
- */
-
- botscreen() {
- move(LINES-1, 0);
- refresh();
- putchar('\n');
- fflush(stdout);
- }
-
-
- /*
- * Clear a line.
- */
-
- clrline(linno) {
- move(linno, 0);
- clrtoeol();
- }
-
-
- #ifdef ACURSES
- /*
- * Ring the bell on the terminal.
- */
-
- beep() {
- putchar('\007');
- fflush(stdout);
- }
- #endif
- !E!O!F!
-
- cat > vnews/dispcntl.c <<\!E!O!F!
- #include "vnews.h"
-
- #ifdef STATTOP
- #define PRLINE 0 /* prompter line */
- #define SPLINE 1 /* secondary prompt line */
- #define ARTWIN 2 /* first line of article window */
- #else
- #define PRLINE (ROWS-1)/* prompter line */
- #define SPLINE (ROWS-2)/* secondary prompt line */
- #define ARTWIN 0 /* first line of article window */
- #endif
-
- int dumpart(), dumpheaders(), dumphelp(), dumphdr();
- int nullsub();
-
- struct window artwin = { /* window containing article */
- 0, 0, dumpart, 2};
- struct window indexwin = { /* window containing article index */
- 0, 0, dumpheaders, 2};
- struct window helpwin = { /* window containing help message */
- 0, 0, dumphelp, 2};
- struct window emptywin = { /* empty window */
- 0, 0, nullsub, 2};
- struct window hdrwin = { /* window containing header */
- 0, 0, dumphdr, 2};
- extern struct svartlist *alptr; /* article list stack */
-
-
-
- /*
- * Open the current article. Returns nonzero on failure.
- */
- openart() {
- struct stat statb;
- FILE *gethead();
-
- if (fp != NULL)
- return 0;
- #ifdef CURSES
- move(0, 0); /* let user know we are thinking */
- refresh();
- #else
- _amove(0, 0); /* let user know we are thinking */
- vflush();
- #endif
- artwin.w_force = 2;
- lastlin = 0;
- fp = fopen(filename, "r");
- if (fp == NULL) {
- msg("Can't open %s", filename);
- artlines = 0;
- artread = 1;
- return TRUE;
- }
- fstat(fileno(fp), &statb);
- artlength = statb.st_size;
- if (gethead(&h, fp) == NULL) {
- msg("Garbled header");
- fclose(fp);
- fp = NULL;
- artlines = 0;
- artread = 1;
- return TRUE;
- }
- { /* strip off any notesfile header */
- register c;
- register char *p = h.h_title + strlen(h.h_title) - 5;
- if (p > h.h_title
- && (strcmp(p, " (nf)") == 0 || strcmp(p, "(nf)\"") == 0)) {
- if ((c = getc(fp)) != '#') {
- ungetc(c, fp);
- } else {
- while ((c = getc(fp)) != '\n' && c != EOF);
- while ((c = getc(fp)) != '\n' && c != EOF);
- while ((c = getc(fp)) != '\n' && c != EOF);
- }
- }
- }
- artbody = ftell(fp);
- fmthdr();
- artlines = lastlin;
- artread = 0;
- if (! cflag && hdrend < ARTWLEN)
- hdronly = 1;
- artwin.w_artlin = 0;
- return 0;
- }
-
-
-
- /*
- * Print out whatever the appropriate header is
- */
- fmthdr() {
- char *vbriefdate();
- char date[64];
-
- if (ngrp) {
- ngrp = 0;
- if (!hflag) {
- sprintf(bfr, "Newsgroup %s", curng->ng_name); tfappend(bfr);
- tfappend("");
- }
- }
- hdrstart = lastlin;
- if (!hflag) {
- sprintf(bfr, "Article %s %s",
- h.h_ident, vbriefdate(h.h_subdate, date));
- tfappend(bfr);
- }
- vhprint(&h, pflag ? 1 : 0);
- sprintf(bfr, "(%d lines)", curart->i_nlines); tfappend(bfr);
- tfappend("");
- hdrend = lastlin;
- }
-
-
-
- /* Arpa format: Sat, 14-May-83 03:45:14 EDT */
- /* Bugs: doesn't work on article with non-arpa dates */
- char *
- vbriefdate(q, date)
- register char *q;
- char *date;
- {
- register char *p;
- register i;
- char day[2];
-
- p = date;
- if (q[3] == ',') {
- for (i = 3 ; --i >= 0 ; )
- *p++ = *q++;
- *p++ = ' ';
- q += 2;
- }
- day[0] = *q++;
- if (*q != ' ' && *q != '-') day[1] = *q++;
- else day[1] = '\0';
- q++;
- for (i = 3 ; --i >= 0 ; )
- *p++ = *q++;
- *p++ = ' ';
- *p++ = day[0];
- if (day[1]) *p++ = day[1];
- q += 5;
- *p++ = ' ';
- if (q[-1] != '0') *p++ = q[-1];
- for (i = 4 ; --i >= 0 ; )
- *p++ = *q++;
- *p++ = '\0';
- return date;
- }
-
- /*
- * Print the file header to the temp file.
- */
- vhprint(hp, verbose)
- register struct arthead *hp;
- int verbose;
- {
- register char *p1, *p2;
- int i;
- char fname[BUFLEN];
-
- fname[0] = '\0'; /* init name holder */
-
- p1 = index(hp->h_from, '('); /* Find the sender's full name. */
- if (p1 == NULL && hset(hp->h_path))
- p1 = index(hp->h_path, '(');
- if (p1 != NULL) {
- strcpy(fname, p1+1);
- p2 = index(fname, ')');
- if (p2 != NULL)
- *p2 = '\0';
- }
-
- sprintf(bfr, "Subject: %s", hp->h_title);
- if ((i = strlen(bfr) - 7) > 9
- && strcmp(bfr + i, " - (nf)") == 0
- && (strncmp(bfr+9, "Re: ", 4) != 0 || i < 9+39))
- bfr[i] = '\0'; /* clobber "- (nf)" */
- tfappend(bfr);
- if (!hflag && hset(hp->h_keywords))
- sprintf(bfr, "Keywords: %s", hp->h_keywords), tfappend(bfr);
- if (verbose) {
- sprintf(bfr, "From: %s", hp->h_from); tfappend(bfr);
- sprintf(bfr, "Path: %s", hp->h_path); tfappend(bfr);
- if (hset(hp->h_organization))
- sprintf(bfr, "Organization: %s", hp->h_organization), tfappend(bfr);
- }
- else {
- if (p1 != NULL)
- *--p1 = '\0'; /* bump over the '(' */
- #ifdef INTERNET
- /*
- * Prefer Path line if it's in internet format, or if we don't
- * understand internet format here, or if there is no reply-to.
- */
- sprintf(bfr, "From: %s", hp->h_from);
- #else
- sprintf(bfr, "Path: %s", tailpath(hp));
- #endif
- if (fname[0] != '\0') {
- strcat(bfr, " (");
- strcat(bfr, fname);
- if (hset(hp->h_organization) && !hflag) {
- strcat(bfr, " @ ");
- strcat(bfr, hp->h_organization);
- }
- strcat(bfr, ")");
- }
- tfappend(bfr);
- if (p1 != NULL)
- *p1 = ' ';
- if (hset(hp->h_ctlmsg)) {
- sprintf(bfr, "Control: %s", hp->h_ctlmsg);
- tfappend(bfr);
- }
- }
-
- if (verbose) {
- sprintf(bfr, "Newsgroups: %s", hp->h_nbuf); tfappend(bfr);
- sprintf(bfr, "Date: %s", hp->h_subdate); tfappend(bfr);
- if (hset(hp->h_sender))
- sprintf(bfr, "Sender: %s", hp->h_sender), tfappend(bfr);
- if (hset(hp->h_replyto))
- sprintf(bfr, "Reply-To: %s", hp->h_replyto), tfappend(bfr);
- if (hset(hp->h_followto))
- sprintf(bfr, "Followup-To: %s", hp->h_followto), tfappend(bfr);
- }
- else if (strcmp(hp->h_nbuf, curng->ng_name) != 0)
- sprintf(bfr, "Newsgroups: %s", hp->h_nbuf), tfappend(bfr);
- }
-
- /*
- * Append file to temp file, handling control characters, folding lines, etc.
- * We don't grow the temp file to more than nlines so that a user won't have
- * to wait for 20 seconds to read in a monster file from net.sources.
- * What we really want is coroutines--any year now.
- */
-
- #define ULINE 0200
- static char *maxcol;
-
-
- appfile(iop, nlines)
- register FILE *iop;
- {
- register int c;
- register char *icol; /* &bfr[0] <= icol <= maxcol */
-
- if (artread || artlines >= nlines)
- return;
- maxcol = bfr;
- icol = bfr;
- while ((c = getc(iop)) != EOF) {
- switch (c) {
- case ' ':
- if (icol == maxcol && icol < bfr + LBUFLEN - 1) {
- *icol++ = ' ';
- maxcol = icol;
- } else {
- icol++;
- }
- break;
- case '\t':
- icol = (icol - bfr &~ 07) + 8 + bfr;
- growline(icol);
- break;
- case '\b':
- if (icol > bfr) --icol;
- break;
- case '\n':
- outline();
- if (artlines >= nlines)
- return;
- icol = bfr;
- break;
- case '\r':
- icol = bfr;
- break;
- case '\f':
- outline(); outline(); outline();
- if (artlines >= nlines)
- return;
- icol = bfr;
- break;
- default:
- if (c < ' ' || c > '~')
- break;
- else if (icol >= bfr + LBUFLEN - 1)
- icol++;
- else if (icol == maxcol) {
- *icol++ = c;
- maxcol = icol; }
- else if (*icol == ' ')
- *icol++ = c;
- else if (c == '_')
- *icol++ |= ULINE;
- else
- *icol++ = (c | ULINE);
- break;
- }
- }
- if (maxcol != bfr) /* file not terminated with newline */
- outline();
- artread++;
- }
-
-
-
- growline(col)
- char *col;
- {
- while (maxcol < col && maxcol < bfr + LBUFLEN - 1)
- *maxcol++ = ' ';
- }
-
-
- outline() {
- *maxcol = '\0';
- if (strncmp(bfr, ">From ", 6) == 0) {
- register char *p;
- for (p = bfr ; (*p = p[1]) != '\0' ; p++);
- }
- tfappend(bfr);
- if (maxcol > bfr)
- artlines = lastlin;
- maxcol = bfr;
- }
-
-
-
- prget(prompter, buf)
- char *prompter, *buf;
- {
- char *p, *q, *r;
- int c, lastc;
-
- curflag = CURP2;
- r = buf;
- lastc = '\0';
- for (;;) {
- *r = '\0';
- p = secpr;
- for (q = prompter ; *q ; q++)
- *p++ = *q;
- for (q = buf ; *q ; q++) {
- if (p < &secpr[SECPRLEN-1] && *q >= ' ' && *p <= '~')
- *p++ = *q;
- }
- *p = '\0';
- c = vgetc();
- if (c == '\n' || c == INTR) {
- break;
- }
- if (c == cerase) {
- if (lastc == '\\')
- r[-1] = c;
- else if (r > buf)
- r--;
- } else if (c == ckill) {
- if (lastc == '\\')
- r[-1] = c;
- else
- r = buf;
- } else if (r < buf + SECPRLEN - 1) {
- *r++ = c;
- } else {
- beep();
- }
- lastc = c;
- }
- curflag = CURHOME;
- secpr[0] = '\0';
- if (c == INTR) {
- nextwin = curwin;
- return 1;
- } else
- return 0;
- }
-
-
-
- /*** Routines for handling temporary file ***/
-
- /*
- * Append to temp file.
- * Long lines are folded.
- */
-
- tfappend(line)
- char *line;
- {
- while (strlen(line) > COLS) {
- tfput(line, lastlin++);
- line += COLS;
- }
- tfput(line, lastlin++);
- }
-
-
- tfput(line, linno)
- char *line;
- {
- register char *p;
- register FILE *rtfp; /* try to make it a litte faster */
- register int i;
-
- p = line;
- #if BSDREL > 7
- i = (COLS + 1) &~ 1;
- #else
- i = COLS;
- #endif
- tfseek(linno, 1);
- rtfp = tfp;
- while (--i >= 0) {
- if (*p)
- putc(*p++, rtfp);
- else
- putc('\0', rtfp);
- }
- tflinno++;
- }
-
-
- tfget(line, linno)
- char *line;
- {
- tfseek(linno, 0);
- #if BSDREL > 7
- fread(line, (COLS + 1) &~ 1, 1, tfp);
- #else
- fread(line, COLS, 1, tfp);
- #endif
- line[COLS] = '\0';
- tflinno++;
- }
-
-
- tfseek(linno, wrflag) {
- static int last = 1;
-
- if (linno != tflinno || wrflag != last) {
- #if BSDREL > 7
- fseek(tfp, (long)linno * (COLS + 1 &~ 1) + tfoffset, 0);
- #else
- fseek(tfp, (long)linno * COLS + tfoffset, 0);
- #endif
- tflinno = linno;
- last = wrflag;
- }
- }
-
-
-
- /*** display management ***/
-
-
- msg(s, a1, a2, a3, a4, a5, a6) char *s; {
- sprintf(secpr, s, a1, a2, a3, a4, a5, a6);
- }
-
-
- scroll(amount) {
- register struct window *w;
-
- w = &artwin;
- if (indexpg)
- w = &indexwin;
- if ((w->w_artlin += amount) < 0)
- w->w_artlin = 0;
- }
-
-
-
- /*
- * Update the display.
- * The display is entirely controlled by this routine,
- * which means that this routine may get pretty snarled.
- */
-
- static struct window *savewin; /* window on last call to updscr */
-
- updscr() {
- int i;
- register struct window *w = curwin;
- char buf[40];
-
- if (checkin())
- return;
- if (w != savewin)
- w->w_force = 2;
- if ((w->w_force || w->w_artlin != w->w_svartlin)
- && (quitflg == 0 || w == &emptywin)) {
- #ifndef CURSES
- if (w->w_force < 2)
- ushift(ARTWIN, ARTWIN+ARTWLEN-1, w->w_artlin - w->w_svartlin);
- #endif
- for (i = ARTWIN ; i < ARTWIN + ARTWLEN ; i++)
- clrline(i);
- (*w->w_dump)(w->w_artlin, ARTWIN, ARTWLEN);
- w->w_force = 0;
- w->w_svartlin = w->w_artlin;
- savewin = w;
- }
- clrline(SPLINE), clrline(PRLINE);
- #ifdef STATTOP
- mvaddstr(PRLINE, 0, prompt);
- #else
- if (strlen(secpr) <= COLS)
- mvaddstr(PRLINE, 0, prompt);
- #endif
- mvaddstr(PRLINE, 48, timestr);
- if (alptr->al_type == SVARTICLE)
- sprintf(buf, "%.18s", curng->ng_name);
- else
- sprintf(buf, "%.18s %d/%d ", curng->ng_name, curind, numthisng);
- mvaddstr(PRLINE, 20, buf);
- if (ismail)
- mvaddstr(PRLINE, 62, ismail > 1? "MAIL" : "mail");
- mvaddstr(SPLINE, 0, secpr);
- if (curflag == CURP1)
- move(PRLINE, strlen(prompt));
- else if (curflag == CURHOME)
- move(0, 0);
- refresh();
- }
-
-
- addnum(n) {
- if (n >= 10)
- addnum(n / 10);
- addch(n % 10 + '0');
- }
-
-
-
- /*
- * Dump the article to the screen. Updscr has already cleared the region.
- */
-
- dumpart(artlin, scrlin, count) {
- register int i;
-
- if (hdronly && count > hdrend - artlin)
- count = hdrend - artlin;
- #ifdef DIGPAGE
- if (endsuba > 0 && count > endsuba - artlin)
- count = endsuba - artlin;
- #endif
- if (count > lastlin - artlin)
- count = lastlin - artlin;
- for (i = 0 ; i < count ; i++) {
- tfget(bfr, artlin + i);
- mvaddstr(scrlin + i, 0, bfr);
- }
- }
-
-
- /*
- * All headers command: show headers for this group.
- */
- dumpheaders(artlin, scrlin, count)
- {
- register int i;
-
- for (i = count ; --i >= 0 ; artlin++, scrlin++) {
- if (artlin == 0) {
- sprintf(bfr, " IND FILE LINES Newsgroup %s, %d articles", curng->ng_name, numthisng);
- mvaddstr(scrlin, 0, bfr);
- } else if (artlin >= 2 && artlin < numthisng + 2) {
- move(scrlin, 0);
- addch(artlin-1 == curind ? '>' :
- (xflag || isunread(thisng[artlin-2].i_artnum) ? ' ': 'D'));
- sprintf(bfr, "%3d%5d%5d %-36s %s",
- artlin-1, thisng[artlin-2].i_artnum, thisng[artlin-2].i_nlines,
- thisng[artlin-2].i_title, thisng[artlin-2].i_from);
- bfr[COLS] = '\0';
- addstr(bfr);
- }
- }
- }
-
-
- /*
- * Dump the help message to the screen. The help msg can't be scrolled.
- */
- dumphelp(artlin, scrlin, count) {
- FILE *helpf;
- #ifndef VHELP
- char VHELP[FPATHLEN];
- #endif
-
- #ifndef VHELP
- sprintf(VHELP, "%s/vnews.help", LIB);
- #endif
- if ((helpf = fopen(VHELP, "r")) == NULL) {
- addstr("Can't open help file");
- return;
- }
- while (fgets(bfr, LBUFLEN, helpf) != NULL) {
- nstrip(bfr);
- mvaddstr(scrlin, 0, bfr);
- scrlin++;
- }
- fclose(helpf);
- }
-
-
- /*
- * Dump the full header on the screen. The header cannot be scrolled.
- * We use the routine appfile to append to the file, which forces us
- * to do some juggling to return to the article.
- */
- dumphdr(artlin, scrlin, count) {
- long saveoff;
- int svartread, svartlines, svlastlin;
- int stoppos = scrlin + count - 1 ;
- register int i;
-
- saveoff = ftell(fp);
- fseek(fp, 0L, 0);
- svartread = artread, svartlines = artlines, svlastlin = lastlin;
- artread = 0;
- appfile(fp, artlines + count);
- if (count > lastlin - svlastlin)
- count = lastlin - svlastlin;
- for (i = 0 ; i < count ; i++) {
- tfget(bfr, svlastlin + i);
- if (bfr[0] == '\0')
- break;
- mvaddstr(scrlin + i, 0, bfr);
- }
- nochange(i + 1, stoppos) ;
- artread = svartread, artlines = svartlines, lastlin = svlastlin;
- fseek(fp, saveoff, 0);
- }
-
-
- nullsub() {;}
- !E!O!F!
-
- cat > vnews/genmakefile <<\!E!O!F!
- : This shell procedure generates the vnews makefile.
-
- LIB=../lib
- if test ! -f $LIB/makedefs
- then echo "$LIB/makedefs not does not exist"
- exit 1
- fi
- exec > temp
- . $LIB/makedefs
- cat <<!
- # Vnews makefile 2.11-B 1/18/85
-
- # definitions
-
- !
- cat $LIB/makedefs
- sed -e 's:$LIB:'$LIB:g <<\!
- LOGDIR =
-
- IBMFLAGS =
- DEBUG = -O
- CFLAGS = $(DEBUG) $(IBMFLAGS) -I$LIB
- LFLAGS = -i $(DEBUG) $(IBMFLAGS)
-
- VOBJECTS = readnews.o vextern.o $(LOGDIR) vreadr.o dispcntl.o artseq.o termio.o virtterm.o
-
- # dependencies
-
- all: makefile vnews
-
- makefile: genmakefile $LIB/makedefs
- genmakefile
- @echo 'Makefile changed, so restart make.'
- @sh -c 'exit 22'
-
- install: all
- -/bin/mv $(BINDIR)/vnews $(BINDIR)/ovnews
- /bin/cp vnews $(BINDIR)/vnews
- -/bin/mv $(LIBDIR)/vnews.help $(LIBDIR)/ovnews.help
- /bin/cp vnews.help $(LIBDIR)/vnews.help
-
- clean:
- rm -f core *.o
-
- readnews.o: readnews.c rparams.h
- $(CC) $(CFLAGS) -c readnews.c
-
- rfuncs.o: rfuncs.c rparams.h
- $(CC) $(CFLAGS) -c rfuncs.c
-
- logdir.o: logdir.c
- $(CC) $(CFLAGS) -c logdir.c
-
- vnews: $(VOBJECTS) $LIB/rpathinit.o $LIB/rlib.a
- $(CC) $(LFLAGS) $(VOBJECTS) $LIB/rpathinit.o $LIB/rlib.a $(TERMCAP) -o $@
-
- vreadr.o dispcntl.o artseq.o termio.o: vnews.h rparams.h
-
- vextern.o: vextern.c rparams.h
-
- VNEWSLINT = artseq.c dispcntl.c readnews.c vextern.c rfuncs.c\
- termio.c virtterm.c vreadr.c\
- $LIB/addrc.c $LIB/afopen.c $LIB/allgroups.c $LIB/bcopy.s\
- $LIB/bfr.c $LIB/bzero.c $LIB/cancel.c $LIB/ckfopen.c\
- $LIB/ckmalloc.c $LIB/dirname.c $LIB/findgroup.c\
- $LIB/genafopen.c $LIB/gethead.c $LIB/getuser.c $LIB/gfopen.c\
- $LIB/hash.c $LIB/hfgets.c $LIB/isadmin.c $LIB/lookup.c\
- $LIB/makehimask.c $LIB/mypathinit.c $LIB/nextgrp.c\
- $LIB/ngchain.c $LIB/ngmatch.c $LIB/nsavestr.c $LIB/nstrip.c\
- $LIB/openrc.c $LIB/pgetuser.c $LIB/prefix.c $LIB/prevgrp.c\
- $LIB/process.c $LIB/read.c $LIB/readinrc.c $LIB/rename.c\
- $LIB/roptions.c $LIB/savestr.c $LIB/scopyn.c $LIB/setupgrp.c\
- $LIB/titmat.c
-
- vnewslint:
- lint -I$LIB -DSPOOLDIR=\"$(SPOOLDIR) -DLIBDIR=\"$(LIBDIR) $(VNEWSLINT) # You must be masochistic
- !
-
- mv temp makefile
- !E!O!F!
- chmod +x vnews/genmakefile
-
- cat > vnews/readnews.c <<\!E!O!F!
- /*
- * readnews - read news articles.
- */
-
- /* static char *SccsId = "%W% %G%"; */
-
- #include "rparams.h"
- #include "artfile.h"
- #include "ng.h"
-
- /*
- * readnews - article reading program
- */
-
-
- /*
- * Authors:
- * Matt Glickman ucbvax!glickman
- * Mark Horton cbosg!mark
- * Stephen Daniels duke!swd
- * Tom Truscott duke!trt
- */
-
- main(argc, argv)
- int argc;
- register char **argv;
- {
- FILE *rcfp;
- FILE *openrc();
- time_t convdate() ;
-
- /* set up defaults and initialize. */
- pathinit();
-
- #ifndef SHELL
- if ((SHELL = getenv("SHELL")) == NULL)
- SHELL = "/bin/sh";
- #endif
- getuser();
-
- rcfp = openrc();
- roptions(argv, rcfp);
-
- if (datebuf) {
- atime = convdate(datebuf) ;
- free(datebuf) ;
- }
-
- /*
- * ALL of the command line has now been processed. (!)
- */
-
- if (sflag) {
- printf("Subscription list: %s\n", sublist);
- xxit(0);
- }
-
- afopen();
- if (xflag)
- readinrc((FILE *)NULL);
- else {
- fseek(rcfp, 0L, 0);
- readinrc(rcfp);
- }
- fclose(rcfp);
-
- #ifdef DEBUG
- fprintf(stderr, "sublist = %s\n", sublist);
- #endif
-
- readr();
-
- fflush(stdout);
- if (xflag || lflag || tflag)
- xxit(0);
- writeoutrc();
- xxit(0);
-
- /* Camel, R.O.H. */
- }
-
-
-
- /*
- * convert a date to UNIX internal format.
- */
-
- time_t
- convdate(s)
- char *s ;
- {
- char buf[512] ;
- FILE *datefp, *popen() ;
- long cgtdate() ;
- long atol() ;
-
- sprintf(buf, "%s/cgtdate '%s'", LIB, s) ;
- if ((datefp = popen(buf, "r")) == NULL || fgets(buf, 512, datefp) == NULL)
- xerror("Can't convert -a date") ;
- return atol(buf) ;
- }
- !E!O!F!
-
- cat > vnews/rfuncs.c <<\!E!O!F!
- /*
- * rfuncs - functions for readnews.
- */
-
- static char *SccsId = "@(#)rfuncs.c 2.9 3/7/83";
-
- #include "rparams.h"
- #include "newsrc.h"
-
- #ifdef notdef
- /*
- * Figure out the number of the largest article in newsgroup ng,
- * and return that value.
- */
- long
- findngsize(ng)
- char *ng;
- {
- FILE *af;
- long s;
- char buf[100], n[100];
-
- af = xfopen(ACTIVE, "r");
- while (fgets(buf, sizeof buf, af)) {
- sscanf(buf, "%s %ld", n, &s);
- if (strcmp(n, ng) == 0) {
- fclose(af);
- return s;
- }
- }
- return 0;
- }
- #endif
-
-
-
- xxit(status)
- int status;
- {
- exit(status);
- }
-
-
- /*
- * Return true if the newsgroup was specified in the -n option.
- */
-
- wewant(name)
- char *name;
- {
- return ngmatch(name, sublist);
- }
- !E!O!F!
-
- cat > vnews/rparams.h <<\!E!O!F!
- /*
- * rparams.h - parameters for readnews, rfuncs, and readr.
- */
-
- /* static char *Rparams = "@(#)rparams.h 2.8 5/28/83"; */
-
- #include "config.h"
- #include <stdio.h>
- #include <signal.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <ctype.h>
- #ifdef SIGXCPU
- /* 4.2BSD moved this file, grumble grumble */
- #include <sys/time.h>
- #else
- #include <time.h>
- #endif
- #include "defs.h"
- #include "arthead.h"
- #include "libextern.h"
- #include "roptions.h"
-
- #define NEXT 0
- #define SPEC 1
-
- #define FORWARD 0
- #define BACKWARD 1
-
- /* external declarations stolen from params.h */
- #ifndef SHELL
- extern char *SHELL;
- #endif
-
- /* external function declarations */
- extern char *strcpy(), *strncpy(), *strcat(), *index(), *rindex();
- extern char *ctime(), *mktemp(), *malloc(), *realloc(), *getenv();
- extern char *arpadate(), *dirname();
- extern time_t time(), getdate(), cgtdate();
- extern int broadcast(), save(), newssave(), ushell(), pshell(), onsig();
- extern long atol();
-
- char *savestr();
-
- /* external declarations specific to readnews */
- extern int mode;
- extern time_t atime;
- !E!O!F!
-
- cat > vnews/termio.c <<\!E!O!F!
- #include "vnews.h"
- #if USGREL >= 30
- #include <termio.h>
- #include <fcntl.h>
- #else
- #include <sgtty.h>
- #endif
- #include <errno.h>
- extern int errno;
- static int alflag; /* set if unprocessed alarm signal */
- static int intflag; /* set if interrupt received */
- #ifdef SIGTSTP
- static int inraw; /* true if in raw mode */
- #endif
- int onstop();
-
-
- /*** Terminal I/O ***/
-
- #define INBUFSIZ 8
-
- char inbuf[INBUFSIZ]; /* input buffer */
- char outbuf[BUFSIZ]; /* output buffer */
- int innleft = 0; /* # of chars in input buffer */
- int outnleft = BUFSIZ; /* room left in output buffer */
- char *innext; /* next input character */
- char *outnext = outbuf; /* next space in output buffer */
- #ifndef CURSES
- #if USGREL >= 30
- int oflags; /* fcntl flags (for nodelay read) */
- #endif
- #endif
-
-
- /*
- * Input a character
- */
-
- vgetc() {
- register c;
- #if BSDREL >= 42
- int readfds, exceptfds;
- #endif
-
- recurse:
- if (--innleft >= 0) {
- c = *innext++;
- } else {
- if (alflag)
- timer();
- updscr(); /* update the display */
- for (;;) {
- if (innleft > 0 || alflag)
- goto recurse;
- intflag = 0;
- #ifndef CURSES
- #if USGREL >= 30
- if (oflags & O_NDELAY) {
- oflags &=~ O_NDELAY;
- fcntl(0, F_SETFL, oflags);
- }
- #endif
- #endif
- #if BSDREL >= 42
- /* Use a select because can be interrupted */
- readfds = 1; exceptfds = 1;
- innleft = select(1, &readfds, 0, &exceptfds, 0);
- if (innleft > 0) {
- if ((innleft = read(0, inbuf, INBUFSIZ)) > 0)
- break;
- }
- #else
- if ((innleft = read(0, inbuf, INBUFSIZ)) > 0)
- break;
- #endif
- if (hupflag)
- return INTR;
- if (innleft == 0 || errno != EINTR)
- abort(); /* "Can't happen" */
- if (intflag) {
- intflag--;
- return INTR;
- }
- }
- innext = inbuf + 1;
- innleft--;
- c = inbuf[0];
- }
- #ifdef V6
- c &= 0177;
- if (c == '\034') /* FS character */
- onquit();
- if (c == '\177') /* DEL */
- onint();
- #endif
- if (c == '\f') {
- clearok(curscr, 1);
- goto recurse;
- }
- if (c == '\r')
- c = '\n';
- return c;
- }
-
-
- /*
- * Push a character back onto the input stream.
- */
-
- pushback(c) {
- if (innext <= inbuf)
- abort();
- *--innext = c;
- innleft++;
- }
-
-
-
- /*
- * Check for terminal input
- */
-
- checkin() {
- #ifndef CURSES
- #if BSDREL > 7
- long count;
-
- #endif
- #endif
- #ifdef STATTOP
- if (innleft > 0)
- #else
- if (innleft > 0 || alflag)
- #endif
- return 1;
- #if !defined(CURSES) && (USGREL >= 30 || BSDREL > 7)
- if (ospeed == B9600)
- return 0;
- vflush();
- if (ospeed <= B300)
- ttyowait();
- #if USGREL >= 30
- if ((oflags & O_NDELAY) == 0) {
- oflags |= O_NDELAY;
- fcntl(0, F_SETFL, oflags);
- }
- if ((innleft = read(0, inbuf, INBUFSIZ)) > 0) {
- innext = inbuf;
- return 1;
- }
- #else
- count = 0; /* in case FIONREAD fails */
- ioctl(0, FIONREAD, &count);
- if (count)
- return 1;
- #endif
- #endif
- return 0;
- }
-
-
-
- /*
- * flush terminal input queue.
- */
-
- clearin() {
- #if USGREL >= 30
- ioctl(0, TCFLSH, 0);
- #else
- #ifdef TIOCFLUSH
- ioctl(0, TIOCFLUSH, 0);
- #else
- struct sgttyb tty;
- gtty(0, &tty);
- stty(0, &tty);
- #endif
- #endif
- innleft = 0;
- }
-
-
- vputc(c) {
- if (--outnleft < 0) {
- vflush();
- outnleft--;
- }
- *outnext++ = c;
- }
-
-
- /*
- * Flush the output buffer
- */
-
- vflush() {
- register char *p;
- register int i;
- #if BSDREL <= 7 && USGREL < 30
- int svalarm = alarm(0); /* signals cause UNIX to drop characters */
- #endif
-
- for (p = outbuf ; p < outnext ; p += i) {
- if (hupflag)
- break;
- if ((i = write(1, p, outnext - p)) < 0) {
- if (errno != EINTR)
- abort(); /* "Can't happen" */
- i = 0;
- }
- }
- outnleft = BUFSIZ;
- outnext = outbuf;
- #if BSDREL <= 7 && USGREL < 30
- alarm(svalarm);
- #endif
- }
-
-
-
-
- /*** terminal modes ***/
-
- #ifndef CURSES
- #if USGREL >= 30
- static struct termio oldtty, newtty;
-
-
- /*
- * Save tty modes
- */
-
- ttysave() {
- if (ioctl(1, TCGETA, &oldtty) < 0)
- xerror("Can't get tty modes");
- newtty = oldtty;
- newtty.c_iflag &=~ (INLCR|IGNCR|ICRNL);
- newtty.c_oflag &=~ (OPOST);
- newtty.c_lflag &=~ (ICANON|ECHO|ECHOE|ECHOK|ECHONL);
- newtty.c_lflag |= (NOFLSH);
- newtty.c_cc[VMIN] = 1;
- newtty.c_cc[VTIME] = 0;
- cerase = oldtty.c_cc[VERASE];
- ckill = oldtty.c_cc[VKILL];
- ospeed = oldtty.c_cflag & CBAUD;
- initterm();
- }
-
-
- /*
- * Set tty modes for visual processing
- */
-
- ttyraw() {
- while (ioctl(1, TCSETAF, &newtty) < 0 && errno == EINTR);
- rawterm();
- }
-
-
-
- ttyowait() { /* wait for output queue to drain */
- while (ioctl(1, TCSETAW, &newtty) < 0 && errno == EINTR);
- }
-
-
- /*
- * Restore tty modes
- */
-
- ttycooked() {
- cookedterm();
- while (ioctl(1, TCSETAF, &oldtty) < 0 && errno == EINTR);
- oflags &=~ O_NDELAY;
- fcntl(0, F_SETFL, oflags) ;
- }
-
- #else
-
- static struct sgttyb oldtty, newtty;
- #if BSDREL >= 40 && BSDREL <= 41
- static struct tchars oldtchars, newtchars;
- #endif
-
-
- /*
- * Save tty modes
- */
-
- ttysave() {
- #ifdef SIGTSTP
- /* How to get/change terminal modes in a job control environment.
- This code is right from the 4.1 bsd jobs(3) manual page.
- */
- #if BSDREL >= 42
- int tpgrp, getpgrp();
- #else
- short tpgrp, getpgrp();
- #endif
-
- retry:
- #if BSDREL >= 42
- sigblock(1<<(SIGTSTP-1) | 1<<(SIGTTIN-1) | 1<<(SIGTTOU-1));
- #else
- sigset(SIGTSTP, SIG_HOLD);
- sigset(SIGTTIN, SIG_HOLD);
- sigset(SIGTTOU, SIG_HOLD);
- #endif
- if (ioctl(2, TIOCGPGRP, &tpgrp) != 0)
- goto nottty;
- if (tpgrp != getpgrp(0)) { /* not in foreground */
- sigset(SIGTTOU, SIG_DFL);
- #if BSDREL >= 42
- sigsetmask(sigblock(0) & ~(1<<(SIGTTOU-1)));
- #endif
- kill(0, SIGTTOU);
- /* job stops here waiting for SIGCONT */
- goto retry;
- }
- sigset(SIGTTIN, onstop);
- sigset(SIGTTOU, onstop);
- sigset(SIGTSTP, onstop);
- #if BSDREL >= 42
- sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1) | 1<<(SIGTTIN-1) | 1<<(SIGTTOU-0)));
- #endif
- #endif
- if (gtty(1, &oldtty) < 0)
- nottty: xerror("Can't get tty modes");
- newtty = oldtty;
- newtty.sg_flags &=~ (CRMOD|ECHO|XTABS);
- #if BSDREL >= 7
- newtty.sg_flags |= CBREAK;
- #else
- newtty.sg_flags |= RAW;
- #endif
- cerase = oldtty.sg_erase;
- ckill = oldtty.sg_kill;
- ospeed = oldtty.sg_ospeed;
- #if BSDREL >= 40 && BSDREL <= 41
- ioctl(1, TIOCGETC, (char *)&oldtchars);
- newtchars = oldtchars;
- if (oldtchars.t_intrc == '\7')
- newtchars.t_intrc = -1;
- #endif
- initterm();
- }
-
-
- /*
- * Set tty modes for visual processing
- */
-
- ttyraw() {
- #ifdef SIGTSTP
- inraw = 1;
- #endif
- while (stty(1, &newtty) < 0 && errno == EINTR);
- #if BSDREL >= 40 && BSDREL <= 41
- ioctl(1, TIOCSETC, (char *) &newtchars);
- #endif
- rawterm();
- }
-
-
-
- ttyowait() { /* wait for output queue to drain */
- #ifdef TIOCDRAIN /* This ioctl is a local mod on linus */
- ioctl(1, TIOCDRAIN, 0);
- #endif
- }
-
-
- /*
- * Restore tty modes
- */
-
- ttycooked() {
- cookedterm();
- while (stty(1, &oldtty) < 0 && errno == EINTR);
- #if BSDREL >= 40 && BSDREL <= 41
- ioctl(1, TIOCSETC, (char *) &oldtchars);
- #endif
- #ifdef SIGTSTP
- inraw = 0;
- #endif
- }
-
- #endif
- #else
- #ifdef HCURSES
-
- ttysave() {
- initscr();
- idlok(stdscr, 1);
- intrflush(curscr, 0);
- cerase = erasechar();
- ckill = killchar();
- }
-
-
- ttyraw() {
- reset_prog_mode();
- cbreak();
- nonl();
- noecho();
- }
-
-
- ttycooked() {
- reset_shell_mode();
- }
-
-
- int _endwin; /* [expletives deleted] */
-
- #else
-
- ttysave() {
- #if USGREL >= 30
- struct termio tty;
- #else
- struct sgttyb tty;
- #endif
-
- initscr();
- #if USGREL >= 30
- ioctl(0, TCGETA, &tty);
- cerase = tty.c_cc[VERASE];
- ckill = tty.c_cc[VKILL];
- #else
- gtty(0, &tty);
- cerase = tty.sg_erase;
- ckill = tty.sg_kill;
- #endif
- }
-
-
- ttyraw() {
- /*
- * Vnews really isn't designed to work with RAW mode, so if you
- * have anything approaching CBREAK mode, use it.
- */
- #ifdef CBREAK
- crmode();
- #else
- raw();
- #endif
- nonl();
- noecho();
- }
-
-
- ttycooked() {
- resetty();
- }
-
- #endif
- #endif CURSES
-
-
-
- /*** signal handlers ***/
-
- onint() {
- signal(SIGINT, onint);
- clearin(); /* flush input queue */
- #if BSDREL >= 40 && BSDREL <= 41
- ioctl(0, TIOCSTI, "\7");
- #else
- intflag++;
- #endif
- }
-
-
- onhup() {
- signal(SIGHUP, onhup);
- hupflag++;
- }
-
-
- onquit() {
- botscreen();
- vflush();
- ttycooked();
- #ifdef COREDUMP
- abort();
- #else
- exit(0);
- #endif
- }
-
- #ifdef SIGTSTP
-
- onstop(signo)
- int signo;
- {
- int restore = inraw;
- int e = errno;
-
- /* restore old terminal state */
- if (restore) {
- botscreen();
- vflush();
- ttycooked();
- }
- sigset(signo, SIG_DFL);
- #if BSDREL >= 42
- sigsetmask(sigblock(0) & ~(1<<(signo-1)));
- #endif
- kill(getpid(), signo); /* stop here until continued */
-
- /* fprintf(stderr,"Vnews restarted."); */
- sigset(signo, onstop);
- /* restore our special terminal state */
- if (restore) {
- ttyraw();
- #ifdef TIOCSTI
- ioctl(0, TIOCSTI, "\f");
- #else
- clearok(curscr, 1); /* doesn't seem to work */
- #endif
- }
- errno = e;
- }
-
- #endif
-
-
-
- /*** alarm handler ***/
-
- /* #include <time.h> */
-
-
- /*
- * Called on alarm signal.
- * Simply sets flag, signal processed later.
- */
-
- onalarm() {
- alflag++;
- }
-
-
- /*
- * Process alarm signal (or start clock)
- */
-
- timer() {
- long tod;
- int hour;
- int i;
- struct tm *t;
- struct stat statb;
- long time();
- static char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
- static long oldmsize = 1000000L;
- static int rccount = 10;
-
- alflag = 0;
- signal(SIGALRM, onalarm);
- time(&tod);
- t = localtime(&tod);
- i = 60 - t->tm_sec;
- alarm(i > 30? 30 : i); /* reset alarm */
- hour = t->tm_hour % 12;
- if (hour == 0) hour = 12;
- sprintf(timestr, "%.3s %d %d:%02d",
- months + 3 * t->tm_mon, t->tm_mday, hour, t->tm_min);
- #ifdef GGRMAIL
- if (mailf == NULL || stat(mailf, &statb) < 0) {
- statb.st_size = 0;
- }
- if(statb.st_size > oldmsize) {
- ismail = 1;
- needbeep++;
- } else if (statb.st_size < oldmsize) {
- ismail = 0;
- }
- oldmsize = statb.st_size;
- #else
- ismail = 0;
- if (mailf != NULL && stat(mailf, &statb) >= 0 && statb.st_size > 0L) {
- ismail = 1;
- if (oldmsize < statb.st_size) {
- ismail = 2; /* new mail */
- needbeep++;
- }
- } else {
- statb.st_size = 0L;
- }
- oldmsize = statb.st_size;
- #endif
- if (uflag && --rccount < 0) {
- writeoutrc();
- if (secpr[0] == '\0')
- strcpy(secpr, ".newsrc updated");
- rccount = 10;
- }
- }
- !E!O!F!
-
- cat > vnews/vextern.c <<\!E!O!F!
- /*
- * rextern - external definitions for readnews
- */
-
- /* static char *SccsId = "@(#)rextern.c 2.5 3/30/83"; */
-
- #include "rparams.h"
-
- time_t atime;
-
- #ifndef SHELL
- char *SHELL;
- #endif
- !E!O!F!
-
- echo Part 6 of 7 extracted.
-
-
-